/****************************************************************************

	COPYRIGHT(C) MAXSI SOFTWARE, JONAS 'SORTIE' TERMANSEN 2008, 2009
	ALL RIGHTS RESERVED

	MaxsiSearch.exe
	A tool used to search for files, faster and more powerful than what
	Windows offers.

	Minidump.cpp
	Crash reporting

****************************************************************************/

#define Application "MaxsiDistribution.dll"

#include <windows.h>
#include <dbghelp.h>
#include <time.h>
#include "MaxsiEngine.h"

namespace MaxsiEngine
{
	class MaxsiEngineMiniDumper;

	class dbghelp_dll : public DLL
	{
	public:
		DECLARE_FUNCTION_WINAPI(BOOL,MiniDumpWriteDump,(
		HANDLE			hProcess,
		DWORD			dwPid,
		HANDLE			hFile,
		MINIDUMP_TYPE	DumpType,

		CONST PMINIDUMP_EXCEPTION_INFORMATION		ExceptionParam,
		CONST PMINIDUMP_USER_STREAM_INFORMATION		UserStreamParam,
		CONST PMINIDUMP_CALLBACK_INFORMATION		CallbackParam));

		virtual bool	Import	( const char* LibraryPath )
		{
			if ( DLL::Import(LibraryPath) )
			{
				IMPORT_FUNCTION(MiniDumpWriteDump);
				return true;
			}
			return false;
		}
	};

	class MaxsiEngineMiniDumper
	{
	public:
		MaxsiEngineMiniDumper(char* AppName);
		~MaxsiEngineMiniDumper();
	};

	static char* ApplicationName;

	LONG WINAPI ExceptionFilter(__in struct _EXCEPTION_POINTERS *ExceptionInfo )
	{
		LONG Result		=	EXCEPTION_CONTINUE_SEARCH;

		// Get the date
		__int64		LocalTime;
		tm			CurrentTime;
		char		CurrentTime_str[26];
		errno_t		err;

		_time64( &LocalTime );

		err = _gmtime64_s( &CurrentTime, &LocalTime );
		if (err)
		{
			char* Error = BuildString(1,"An unhandled error occured in "Application". Maxsi Engine failed to generate a minidump file because _gmtime64_s failed. " SupportId(31));
			MessageBoxA(NULL,Error,"Maxsi Engine",MB_ICONERROR);
			delete[] Error;
			return Result;				
		}

		err = asctime_s(CurrentTime_str, 26, &CurrentTime);
		if (err)
		{
			char* Error = BuildString(1,"An unhandled error occured in "Application". Maxsi Engine failed to generate a minidump file because asctime_s failed. " SupportId(32));
			MessageBoxA(NULL,Error,"Maxsi Engine",MB_ICONERROR);
			delete[] Error;
			return Result;		
		}

		// Now that we got the date, proceed and generate the filename

		char*		Dir		=	GetWorkingDirectory();
		char*		File	=	BuildString(5,Dir,Application,"_v" __DATE__ "_date",CurrentTime_str,".mdmp");
		str_replace(File+2,":","_"); // plus too to avoid c: becoming c_
		str_replace(File+2,"\n","_"); // asctime_s adds a line break? wut
		
		char*		DllFile	=	BuildString(2,Dir,"dbghelp.dll");

		// Load the dbghelp.dll
		
		dbghelp_dll* dll = new dbghelp_dll;

		if ( !dll->Import(DllFile) )
		{
			dll->Import("dbghelp.dll"); // Perhaps the system has a proper copy
		}
		
		if (dll->Executable!=NULL)
		{
			// create the file
			HANDLE hFile = CreateFileA( File, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
										FILE_ATTRIBUTE_NORMAL, NULL );

			if (hFile!=INVALID_HANDLE_VALUE)
			{
				_MINIDUMP_EXCEPTION_INFORMATION ExInfo;

				ExInfo.ThreadId = ::GetCurrentThreadId();
				ExInfo.ExceptionPointers = ExceptionInfo;
				ExInfo.ClientPointers = NULL;

				// write the dump
				BOOL bOK = dll->MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)(MiniDumpNormal | MiniDumpWithDataSegs), &ExInfo, NULL, NULL );
				if (bOK)
				{
					char* Error = BuildString(3,"An unhandled error occured in "Application". A minidump file containing information about how this crash happened has been saved to\n\n",File,"\n\nPlease send this file to the developers of this product. " SupportId(33));
					MessageBoxA(NULL,Error,"Maxsi Engine",MB_ICONERROR);
					delete[] Error;
					Result = EXCEPTION_EXECUTE_HANDLER;
				}
				else
				{				

					char* Error = BuildString(1,"An unhandled error occured in "Application". Maxsi Engine failed to generate a minidump file because something went wrong while writing the minidump. " SupportId(34));
					MessageBoxA(NULL,Error,"Maxsi Engine",MB_ICONERROR);
					delete[] Error;
				}
				CloseHandle(hFile);
			}
			else
			{
				char* Error = BuildString(3,"An unhandled error occured in "Application". Maxsi Engine failed to generate a minidump file because the target file path couldn't be opened\n\n",File, "\n\n" SupportId(35));
				MessageBoxA(NULL,Error,"Maxsi Engine",MB_ICONERROR);
				delete[] Error;
			}
		}
		else
		{
			char* Error = BuildString(1,"An unhandled error occured in "Application". Maxsi Engine failed to generate a minidump file because dbghelp.dll wasn't found. " SupportId(36));
			MessageBoxA(NULL,Error,"Maxsi Engine",MB_ICONERROR);
			delete[] Error;
		}

		// Clean up
		delete[]	File;
		delete[]	Dir;
		delete[]	DllFile;
		delete		dll;
		return Result;
	}




	MaxsiEngineMiniDumper::MaxsiEngineMiniDumper(char* AppName)
	{
		ApplicationName = BuildString(1,AppName);
		SetUnhandledExceptionFilter(MaxsiEngine::ExceptionFilter);
	}

	MaxsiEngineMiniDumper::~MaxsiEngineMiniDumper()
	{
		if ( ApplicationName )
		{
			delete[] ApplicationName;
		}
	}	

	MaxsiEngine::MaxsiEngineMiniDumper MiniDumper(Application);

}